using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using UwinEducation.Domain.Entities;
using UwinEducation.Domain.IRepositories;
using UwinEducation.Infrastructure.Persistence;
using UwinEducation.Shared.Enums;
using UwinEducation.Shared.Models;

namespace UwinEducation.Infrastructure.Repositories
{
    /// <summary>
    /// 学生课表详情仓储实现
    /// </summary>
    public class StudentScheduleDetailsRepository
        : Repository<StudentScheduleDetails, Guid>,
            IStudentScheduleDetailsRepository
    {
        public StudentScheduleDetailsRepository(ApplicationDbContext context)
            : base(context) { }

        /// <summary>
        /// 获取订单详情下的所有课表详情
        /// </summary>
        public async Task<List<StudentScheduleDetails>> GetByOrderDetailIdAsync(Guid orderDetailId)
        {
            return await _context
                .StudentScheduleDetails.Include(sd => sd.OrderDetail)
                .Include(sd => sd.TeacherScheduleDetails)
                .Include(sd => sd.TeacherScheduleDetails.TeacherSchedule)
                .Include(sd => sd.TeacherScheduleDetails.TeacherSchedule.Teacher)
                .Include(sd => sd.TeacherScheduleDetails.TeacherSchedule.Course)
                .Where(sd => sd.OrderDetailId == orderDetailId)
                .OrderBy(sd => sd.TeacherScheduleDetails.StartTime)
                .ToListAsync();
        }

        /// <summary>
        /// 获取教师课表详情下的所有学生课表
        /// </summary>
        public async Task<List<StudentScheduleDetails>> GetByTeacherScheduleDetailsIdAsync(
            Guid teacherScheduleDetailsId
        )
        {
            return await _context
                .StudentScheduleDetails.Include(sd => sd.OrderDetail)
                .Include(sd => sd.OrderDetail.Student)
                .Include(sd => sd.TeacherScheduleDetails)
                .Where(sd => sd.TeacherScheduleDetailsId == teacherScheduleDetailsId)
                .OrderBy(sd => sd.CreatedAt)
                .ToListAsync();
        }

        public async Task<List<StudentScheduleDetails>> GetByTeacherScheduleDetailsIdAsync(List<Guid> teacherScheduleDetailsIds, Guid? studentId)
        {

            if (studentId.HasValue)
            {
                return await _context
                    .StudentScheduleDetails.Include(sd => sd.OrderDetail.Student)
                    .Where(sd => teacherScheduleDetailsIds.Contains(sd.TeacherScheduleDetailsId) && sd.OrderDetail.StudentId == studentId)
                    .OrderBy(sd => sd.CreatedAt)
                    .ToListAsync();
            }
            else
            {
                return await _context
                .StudentScheduleDetails.Include(sd => sd.OrderDetail.Student)
                .Where(sd => teacherScheduleDetailsIds.Contains(sd.TeacherScheduleDetailsId))
                .OrderBy(sd => sd.CreatedAt)
                .ToListAsync();
            }


        }

        /// <summary>
        /// 根据状态获取学生课表详情
        /// </summary>
        public async Task<List<StudentScheduleDetails>> GetByStatusAsync(ScheduleStatus status)
        {
            return await _context
                .StudentScheduleDetails.Include(sd => sd.OrderDetail)
                .Include(sd => sd.TeacherScheduleDetails)
                .Where(sd => sd.Status == status)
                .OrderBy(sd => sd.TeacherScheduleDetails.StartTime)
                .ToListAsync();
        }

        /// <summary>
        /// 获取指定时间范围内的学生课表详情
        /// </summary>
        public async Task<List<StudentScheduleDetails>> GetByDateRangeAsync(
            Guid orderDetailId,
            DateTime startTime,
            DateTime endTime
        )
        {
            return await _context
                .StudentScheduleDetails.Include(sd => sd.OrderDetail)
                .Include(sd => sd.TeacherScheduleDetails)
                .Where(sd =>
                    sd.OrderDetailId == orderDetailId
                    && sd.TeacherScheduleDetails.StartTime >= startTime
                    && sd.TeacherScheduleDetails.EndTime <= endTime
                )
                .OrderBy(sd => sd.TeacherScheduleDetails.StartTime)
                .ToListAsync();
        }

        /// <summary>
        /// 批量添加学生课表详情
        /// </summary>
        public async Task AddRangeAsync(List<StudentScheduleDetails> details)
        {
            await _context.StudentScheduleDetails.AddRangeAsync(details);
            await _context.SaveChangesAsync();
        }

        /// <summary>
        /// 批量更新学生课表详情
        /// </summary>
        public async Task UpdateRangeAsync(List<StudentScheduleDetails> details)
        {
            _context.StudentScheduleDetails.UpdateRange(details);
            await _context.SaveChangesAsync();
        }

        /// <summary>
        /// 批量删除学生课表详情
        /// </summary>
        public async Task DeleteRangeAsync(List<StudentScheduleDetails> details)
        {
            _context.StudentScheduleDetails.RemoveRange(details);
            await _context.SaveChangesAsync();
        }

        /// <summary>
        /// 检查时间冲突
        /// </summary>
        public async Task<bool> HasTimeConflictAsync(
            Guid orderDetailId,
            DateTime startTime,
            DateTime endTime,
            Guid? excludeId = null
        )
        {
            var query = _context
                .StudentScheduleDetails.Include(sd => sd.TeacherScheduleDetails)
                .Where(sd =>
                    sd.OrderDetailId == orderDetailId
                    && sd.Status == ScheduleStatus.Normal
                    && (
                        (
                            sd.TeacherScheduleDetails.StartTime <= startTime
                            && sd.TeacherScheduleDetails.EndTime > startTime
                        )
                        || (
                            sd.TeacherScheduleDetails.StartTime < endTime
                            && sd.TeacherScheduleDetails.EndTime >= endTime
                        )
                        || (
                            sd.TeacherScheduleDetails.StartTime >= startTime
                            && sd.TeacherScheduleDetails.EndTime <= endTime
                        )
                    )
                );

            if (excludeId.HasValue)
            {
                query = query.Where(sd => sd.Id != excludeId.Value);
            }

            return await query.AnyAsync();
        }

        /// <summary>
        /// 获取详情
        /// </summary>
        public override async Task<StudentScheduleDetails> GetByIdAsync(Guid id)
        {
            return await _context
                .StudentScheduleDetails.Include(sd => sd.OrderDetail)
                .Include(sd => sd.OrderDetail.Student)
                .Include(sd => sd.TeacherScheduleDetails)
                .Include(sd => sd.TeacherScheduleDetails.TeacherSchedule)
                .Include(sd => sd.TeacherScheduleDetails.TeacherSchedule.Teacher)
                .Include(sd => sd.TeacherScheduleDetails.TeacherSchedule.Course)
                .FirstOrDefaultAsync(sd => sd.Id == id);
        }

        /// <summary>
        /// 分页查询学生课表详情
        /// </summary>
        //public async Task<PagedResult<StudentScheduleDetails>> GetPagedAsync(
        //    StudentScheduleDetailsPageRequest request
        //)
        //{
        //    // 创建基础查询
        //    var query = _context
        //        .StudentScheduleDetails
        //        .Where(o => !o.OrderDetail.Student.IsDeleted) // 过滤已删除的学生
        //        .AsNoTracking() // 提升查询性能
        //        .AsQueryable();

        //    // 应用筛选条件
        //    if (request.StartDate.HasValue)
        //    {
        //        query = query.Where(sd =>
        //            sd.TeacherScheduleDetails.StartTime >= request.StartDate.Value
        //        );
        //    }

        //    if (request.EndDate.HasValue)
        //    {
        //        query = query.Where(sd =>
        //            sd.TeacherScheduleDetails.StartTime <= request.EndDate.Value
        //        );
        //    }

        //    if (!string.IsNullOrEmpty(request.Remarks))
        //    {
        //        query = query.Where(sd => sd.Remarks.Contains(request.Remarks));
        //    }

        //    if (request.TeacherScheduleDetailsId.HasValue)
        //    {
        //        query = query.Where(sd =>
        //            sd.TeacherScheduleDetailsId == request.TeacherScheduleDetailsId.Value
        //        );
        //    }
        //    if (request.StudentId.HasValue)
        //    {
        //        query = query.Where(sd => sd.OrderDetail.StudentId == request.StudentId.Value);
        //    }

        //    // 计算总记录数
        //    var total = await query.CountAsync();

        //    // 使用投影查询获取分页数据，显式选择需要的属性，避免循环引用
        //    var items = await query
        //        .Skip((request.PageIndex - 1) * request.PageSize)
        //        .Take(request.PageSize)
        //        .Select(sd => new StudentScheduleDetails
        //        {
        //            Id = sd.Id,
        //            OrderDetailId = sd.OrderDetailId,
        //            TeacherScheduleDetailsId = sd.TeacherScheduleDetailsId,
        //            Status = sd.Status,
        //            Reason = sd.Reason,
        //            IsForceCheck = sd.IsForceCheck,
        //            Remarks = sd.Remarks,
        //            CourseType = sd.CourseType,
        //            CreatedAt = sd.CreatedAt,
        //            UpdatedAt = sd.UpdatedAt,

        //            // 显式创建 OrderDetail，不包含 StudentScheduleDetails
        //            OrderDetail = new OrderDetail
        //            {
        //                Id = sd.OrderDetail.Id,
        //                OrderId = sd.OrderDetail.OrderId,
        //                StudentId = sd.OrderDetail.StudentId,
        //                TeacherScheduleId = sd.OrderDetail.TeacherScheduleId,
        //                UnitPrice = sd.OrderDetail.UnitPrice,
        //                IsForceCheck = sd.OrderDetail.IsForceCheck,

        //                // 只包含必要的学生信息
        //                Student = sd.OrderDetail.Student != null ? new Student
        //                {
        //                    Id = sd.OrderDetail.Student.Id,
        //                    Name = sd.OrderDetail.Student.Name,
        //                    StudentNo = sd.OrderDetail.Student.StudentNo,
        //                    School = sd.OrderDetail.Student.School,
        //                    Grade = sd.OrderDetail.Student.Grade,
        //                    Phone = sd.OrderDetail.Student.Phone,
        //                    Email = sd.OrderDetail.Student.Email,
        //                    Remarks = sd.OrderDetail.Student.Remarks,
        //                    CreatedAt = sd.OrderDetail.Student.CreatedAt
        //                } : null,

        //                // 不包含 StudentScheduleDetails
        //                StudentScheduleDetails = null
        //            },

        //            // 只包含必要的教师课表详情
        //            TeacherScheduleDetails = sd.TeacherScheduleDetails != null ? new TeacherScheduleDetails
        //            {
        //                Id = sd.TeacherScheduleDetails.Id,
        //                TeacherScheduleId = sd.TeacherScheduleDetails.TeacherScheduleId,
        //                StartTime = sd.TeacherScheduleDetails.StartTime,
        //                EndTime = sd.TeacherScheduleDetails.EndTime,
        //                Status = sd.TeacherScheduleDetails.Status,
        //                Reason = sd.TeacherScheduleDetails.Reason,
        //                CourseType = sd.TeacherScheduleDetails.CourseType
        //            } : null
        //        })
        //        .ToListAsync();

        //    return new PagedResult<StudentScheduleDetails> { Total = total, Items = items };
        //}



        /// <summary>
        /// 分页查询学生课表详情
        /// </summary>
        public async Task<PagedResult<StudentScheduleDetails>> GetPagedAsync(
            StudentScheduleDetailsPageRequest request
        )
        {
            // //TODO: 如果学生不存在，则不包含
            var query = _context
                .StudentScheduleDetails.Where(sd => sd.Status == ScheduleStatus.Normal)
                .Include(sd => sd.OrderDetail).ThenInclude(od => od.Student).Where(o => !o.OrderDetail.Student.IsDeleted)
                .Include(sd => sd.OrderDetail.Order) // 添加Order关联
                .Include(sd => sd.OrderDetail.TeacherSchedule).ThenInclude(ts => ts.Teacher)
                .Include(sd => sd.OrderDetail.TeacherSchedule).ThenInclude(ts => ts.Course)
                .Include(sd => sd.OrderDetail.TeacherSchedule).ThenInclude(ts => ts.Classroom)
                .Include(sd => sd.TeacherScheduleDetails)
                .Where(sd => sd.OrderDetail.Order != null && sd.OrderDetail.TeacherSchedule != null && sd.OrderDetail.TeacherSchedule.Teacher != null && sd.OrderDetail.TeacherSchedule.Course != null)  
                .AsNoTracking() // 添加 AsNoTracking 提升查询性能
                .AsSplitQuery() // 使用分割查询避免笛卡尔积
                .AsQueryable();

            if (request.StartDate.HasValue)
            {
                query = query.Where(sd =>
                    sd.TeacherScheduleDetails.StartTime >= request.StartDate.Value
                );
            }

            if (request.EndDate.HasValue)
            {
                query = query.Where(sd =>
                    sd.TeacherScheduleDetails.StartTime <= request.EndDate.Value
                );
            }
            if (!string.IsNullOrEmpty(request.StudentNo))
            {
                query = query.Where(sd => sd.OrderDetail.Student.StudentNo.Contains(request.StudentNo));
            }
            if (!string.IsNullOrEmpty(request.Name))
            {
                query = query.Where(sd => sd.OrderDetail.Student.Name.Contains(request.Name));
            }

            if (!string.IsNullOrEmpty(request.Remarks))
            {
                query = query.Where(sd => sd.Remarks.Contains(request.Remarks));
            }

            if (request.TeacherScheduleDetailsId.HasValue)
            {
                query = query.Where(sd =>
                    sd.TeacherScheduleDetailsId == request.TeacherScheduleDetailsId.Value
                );
            }
            if (request.StudentId.HasValue)
            {
                query = query.Where(sd => sd.OrderDetail.StudentId == request.StudentId.Value);
            }


            var total = await query.CountAsync();
            var items = await query
                .Skip((request.PageIndex - 1) * request.PageSize)
                .Take(request.PageSize)
                .ToListAsync();

            return new PagedResult<StudentScheduleDetails> { Total = total, Items = items };
        }
        /// <summary>
        /// 根据学生ID和教师课表ID获取学生课表详情
        /// </summary>
        public async Task<StudentScheduleDetails> GetByOrderDetailIdAndTeacherScheduleIdAsync(
            Guid orderDetailId,
            Guid teacherScheduleDetailsId
        )
        {
            return await _context.StudentScheduleDetails.FirstOrDefaultAsync(sd =>
                sd.OrderDetailId == orderDetailId
                && sd.TeacherScheduleDetailsId == teacherScheduleDetailsId
            );
        }

        public async Task<int> GetUsedCapacityByTeacherScheduleIdAsync(Guid teacherScheduleId, Guid? studentId)
        {
            //如果studentId不为空，则统计不包含studentId的学生的数量
            if (studentId.HasValue)
            {
                return await _context
                    .StudentScheduleDetails.Include(sd => sd.OrderDetail.Student)
                    .Where(sd =>
                        sd.OrderDetail.Student!=null&&sd.TeacherScheduleDetails.TeacherScheduleId == teacherScheduleId
                        && sd.OrderDetail.StudentId != studentId
                    )
                    .GroupBy(sd => new
                    {
                        sd.TeacherScheduleDetails.TeacherScheduleId,
                        sd.OrderDetail.StudentId,
                    }) // 按两个字段分组
                    .Select(g => g.Key.StudentId) // 选择每组的StudentId
                    .Distinct() // 去重
                    .CountAsync(); // 计数不同学生的数量
            }
            else
            {
                return await _context
                    .StudentScheduleDetails.Where(sd =>
                        sd.TeacherScheduleDetails.TeacherScheduleId == teacherScheduleId
                    )
                    .GroupBy(sd => new
                    {
                        sd.TeacherScheduleDetails.TeacherScheduleId,
                        sd.OrderDetail.StudentId,
                    }) // 按两个字段分组
                    .Select(g => g.Key.StudentId) // 选择每组的StudentId
                    .Distinct() // 去重
                    .CountAsync(); // 计数不同学生的数量
            }
        }

        /// <summary>
        /// 根据学生ID和教师课表详情ID获取学生课表详情
        /// </summary>
        public async Task<StudentScheduleDetails> GetByStudentIdAndTeacherScheduleDetailsIdAsync(
            Guid studentId,
            Guid teacherScheduleDetailsId
        )
        {
            return await _context.StudentScheduleDetails.FirstOrDefaultAsync(sd =>
                sd.OrderDetail.StudentId == studentId
                && sd.TeacherScheduleDetailsId == teacherScheduleDetailsId
            );
        }

        /// <summary>
        /// 根据学生ID获取学生课表详情
        /// </summary>
        public async Task<List<StudentScheduleDetails>> GetByStudentIdAsync(
            Guid studentId,
            DateTime startTime,
            DateTime endTime
        )
        {
            //TeacherScheduleDetails.StartTime包含在startTime和endTime之间
            return await _context
                .StudentScheduleDetails.Include(sd => sd.TeacherScheduleDetails)
                .Include(sd => sd.TeacherScheduleDetails.TeacherSchedule)
                .Include(sd => sd.TeacherScheduleDetails.TeacherSchedule.Teacher)
                .Include(sd => sd.TeacherScheduleDetails.TeacherSchedule.Course)
                .Where(sd =>
                    sd.OrderDetail.StudentId == studentId
                    && (
                        (
                            sd.TeacherScheduleDetails.StartTime >= startTime
                            && sd.TeacherScheduleDetails.StartTime <= endTime
                        )
                        || (
                            sd.TeacherScheduleDetails.EndTime >= startTime
                            && sd.TeacherScheduleDetails.EndTime <= endTime
                        )
                    )
                )
                .ToListAsync();
        }
    }
}
